/**
 * Copyright (c) 2019, Freqchip
 * 
 * All rights reserved.
 * 
 * 
 */
 
 /*
 * INCLUDES (包含头文件)
 */
#include <stdbool.h>

#include "co_printf.h"

#include "gap_api.h"
#include "gatt_api.h"
#include "co_log.h"
#include "simple_gatt_service.h"
#include "ble_simple_peripheral.h"
#include "ota_service.h"
#define LINK_RSSI_REPORT        0
/*
 * MACROS (宏定义)
 */

#define BLE_NAME_STR	'S','i','m','p','l','e',' ','P','e','r','i','p','h','e','r','a','l'
#define BLE_NAME_LEN	(0x11+1) //BLE_NAME_LEN = (BLE_NAME_STR+1)
/*
 * CONSTANTS (常量定义)
 */

// GAP - Advertisement data (max size = 31 bytes, though this is
// best kept short to conserve power while advertisting)
// GAP-广播包的内容,最长31个字节.短一点的内容可以节省广播时的系统功耗.
static uint8_t adv_data[] =
{
  // service UUID, to notify central devices what services are included
  // in this peripheral. 告诉central本机有什么服务, 但这里先只放一个主要的.
  0x03,   // length of this data
  GAP_ADVTYPE_16BIT_MORE,      // some of the UUID's, but not all
  0xFF,
  0xFE,
};

// GAP - Scan response data (max size = 31 bytes, though this is
// best kept short to conserve power while advertisting)
// GAP-Scan response内容,最长31个字节.短一点的内容可以节省广播时的系统功耗.
static uint8_t scan_rsp_data[] =
{
  // complete name 设备名字
  BLE_NAME_LEN,   // length of this data
  GAP_ADVTYPE_LOCAL_NAME_COMPLETE,
  BLE_NAME_STR,
  // Tx power level 发射功率
  0x02,   // length of this data
  GAP_ADVTYPE_POWER_LEVEL,
  0,	   // 0dBm
};

extern const char *app_tag;
/*
 * TYPEDEFS (类型定义)
 */

/*
 * GLOBAL VARIABLES (全局变量)
 */

/*
 * LOCAL VARIABLES (本地变量)
 */


 
/*
 * LOCAL FUNCTIONS (本地函数)
 */
static void sp_start_adv(void);
/*
 * EXTERN FUNCTIONS (外部函数)
 */

/*
 * PUBLIC FUNCTIONS (全局函数)
 */

/** @function group ble peripheral device APIs (ble外设相关的API)
 * @{
 */

/*********************************************************************
 * @fn      app_gap_evt_cb
 *
 * @brief   Application layer GAP event callback function. Handles GAP evnets.
 *
 * @param   p_event - GAP events from BLE stack.
 *       
 *
 * @return  None.
 */
void app_gap_evt_cb(gap_event_t *p_event)
{
    switch(p_event->type)
    {
        case GAP_EVT_ADV_END:
        {
            LOG_INFO(app_tag, "adv_end,status:0x%02x\r\n",p_event->param.adv_end.status);
        }
        break;
        
        case GAP_EVT_ALL_SVC_ADDED:
        {
            LOG_INFO(app_tag, "All service added\r\n");
            sp_start_adv();
        }
        break;

        case GAP_EVT_SLAVE_CONNECT:
        {
            LOG_INFO(app_tag, "slave[%d],connect. link_num:%d\r\n",p_event->param.slave_connect.conidx,gap_get_connect_num());
        }
        break;

        case GAP_EVT_DISCONNECT:
        {
            LOG_INFO(app_tag, "Link[%d] disconnect,reason:0x%02X\r\n",p_event->param.disconnect.conidx
                      ,p_event->param.disconnect.reason);
            gap_start_advertising(0);
        }
        break;

        case GAP_EVT_LINK_PARAM_REJECT:
        {
            LOG_INFO(app_tag, "Link[%d]param reject,status:0x%02x\r\n"
                      ,p_event->param.link_reject.conidx,p_event->param.link_reject.status);
        }
            break;

        case GAP_EVT_LINK_PARAM_UPDATE:
        {
            LOG_INFO(app_tag, "Link[%d]param update,interval:%d,latency:%d,timeout:%d\r\n",p_event->param.link_update.conidx
                      ,p_event->param.link_update.con_interval,p_event->param.link_update.con_latency,p_event->param.link_update.sup_to);
        }
            break;

        case GAP_EVT_PEER_FEATURE:
        {
            LOG_INFO(app_tag, "peer[%d] feats ind\r\n",p_event->param.peer_feature.conidx);
        }
            break;

        case GAP_EVT_MTU:
        {
            LOG_INFO(app_tag, "mtu update,conidx=%d,mtu=%d\r\n"
                      ,p_event->param.mtu.conidx,p_event->param.mtu.value);
        } 
            break;
        
        case GAP_EVT_LINK_RSSI:
        {
            LOG_INFO(app_tag, "link rssi %d\r\n",p_event->param.link_rssi);
        } 
            break;
        
        case GAP_SEC_EVT_BOND_START:
        {
            LOG_INFO(app_tag, "bond start\r\n");
            gap_pairing_rsp(true);
        }
            break;
        
        case GAP_SEC_EVT_PIN_CODE_REQ:
        {
            LOG_INFO(app_tag, "pin code req[%d]:%02x\r\n",p_event->param.pin_code_req.conidx,p_event->param.pin_code_req.tk_type);
        }
            break;
        
        case GAP_SEC_EVT_SLAVE_ENCRYPT:
        {
            LOG_INFO(app_tag, "slave[%d]_encrypted\r\n",p_event->param.slave_encrypt_conidx);
        } 
            break;
        
        case GAP_SEC_EVT_LTK_MISSING:
        {
            LOG_INFO(app_tag, "ltk miss conidx:%d\r\n",p_event->param.bond_ltk_missing_conidx);
        }
            break;
            

        default:
            break;
    }
}


/*********************************************************************
 * @fn      sp_start_adv
 *
 * @brief   Set advertising data & scan response & advertising parameters and start advertising
 *
 * @param   None. 
 *       
 *
 * @return  None.
 */
static void sp_start_adv(void)
{
    // Set advertising parameters
    gap_adv_param_t adv_param;
    adv_param.adv_mode = GAP_ADV_MODE_UNDIRECT;
    adv_param.adv_addr_type = GAP_ADDR_TYPE_PUBLIC;//GAP_ADDR_TYPE_PUBLIC;
    adv_param.adv_chnl_map = GAP_ADV_CHAN_ALL;
    adv_param.adv_filt_policy = GAP_ADV_ALLOW_SCAN_ANY_CON_ANY;
    adv_param.adv_intv_min = 1000;
    adv_param.adv_intv_max = 1000;
        
    gap_set_advertising_param(&adv_param);
    
    // Set advertising data & scan response data
	gap_set_advertising_data(adv_data, sizeof(adv_data));
	gap_set_advertising_rsp_data(scan_rsp_data, sizeof(scan_rsp_data));
    // Start advertising
	co_printf("Start advertising...\r\n");
	gap_start_advertising(0);
}


/*********************************************************************
 * @fn      simple_peripheral_init
 *
 * @brief   Initialize simple peripheral profile, BLE related parameters.
 *
 * @param   None. 
 *       
 *
 * @return  None.
 */
void simple_peripheral_init(void)
{
    // set local device name
    uint8_t local_name[] = {BLE_NAME_STR};
    gap_dev_name_set(local_name, sizeof(local_name));
    
    // Initialize security related settings.
    gap_security_param_t param =
    {
        .mitm = false,
        .ble_secure_conn = false,
        .io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT,
        .pair_init_mode = GAP_PAIRING_MODE_WAIT_FOR_REQ,
        .bond_auth = false,
        .password = 0,
    };
    
    gap_security_param_init(&param);   
    gap_set_cb_func(app_gap_evt_cb);
//  gap_bond_manager_init(BLE_BONDING_INFO_SAVE_ADDR, BLE_REMOTE_SERVICE_SAVE_ADDR, 8, true);
//  gap_bond_manager_delete_all();
	mac_addr_t addr;	

	addr.addr[0] = 0x55;
	addr.addr[1] = 0x44;
	addr.addr[2] = 0x33;
	addr.addr[3] = 0x22;
	addr.addr[4] = 0x11;
	addr.addr[5] = 0x20;
		
	enum ble_addr_type type=BLE_ADDR_TYPE_PRIVATE;
	//gap_address_set(&addr,BLE_ADDR_TYPE_PRIVATE);
	gap_address_get(&addr,&type);
	co_printf("Local BDADDR: 0x%2X%2X%2X%2X%2X%2X\r\n", addr.addr[0], addr.addr[1], addr.addr[2], addr.addr[3], addr.addr[4], addr.addr[5]);


	// Adding services to database
	sp_gatt_add_service();  
	ota_gatt_add_service();
#if LINK_RSSI_REPORT
    gap_set_link_rssi_report(true);
#endif
}

#if LINK_RSSI_REPORT
 __attribute__((section("ram_code"))) void gap_rssi_ind(int8_t rssi, uint8_t conidx)
{
    co_printf("rssi: link=%d, rssi=%d.\r\n", conidx, rssi);
}
#endif


